package main

import (
	"context"
	"encoding/json"
	"fmt"
	"log"
	"os"
	"time"

	"github.com/chromedp/cdproto/cdp"
	"github.com/chromedp/cdproto/network"
	"github.com/chromedp/chromedp"
)

const (
	loginURL   = "https://devops.dev.easyops.local/next/auth/login"
	cookieFile = "cookies.json"
)

func initAllocator() (context.Context, context.CancelFunc) {
	opts := append(chromedp.DefaultExecAllocatorOptions[:],
		chromedp.Flag("headless", false),
		chromedp.Flag("enable-gpu", true),
		//chromedp.Flag("use-gl", "desktop"),
		//chromedp.Flag("ignore-gpu-blocklist", true),
		chromedp.Flag("disk-cache-dir", "/tmp/cache"),
		//chromedp.Flag("disk-cache-size", 104857600),
		//chromedp.Flag("disable-logging", true),
		//chromedp.Flag("window-size", "1920,1080"),
		//chromedp.Flag("pageLoadStrategy", "eager"),
	)
	allocCtx, cancel := chromedp.NewExecAllocator(context.Background(), opts...)
	return allocCtx, cancel
}

// performLoginAndSave 登录并保存 cookies
func performLoginAndSave(ctx context.Context, username, password string) error {
	// 启用 network 域
	if err := chromedp.Run(ctx, network.Enable()); err != nil {
		return fmt.Errorf("chromedp.Run 启用 network 域 err:%v", err)
	}

	// 登录操作
	if err := chromedp.Run(ctx,
		chromedp.Navigate(loginURL),
		chromedp.WaitVisible(`#general_login_username`, chromedp.ByID),
		chromedp.SendKeys(`#general_login_username`, username, chromedp.ByID),
		chromedp.SendKeys(`#general_login_password`, password, chromedp.ByID),
		chromedp.Click(`button[type=submit]`, chromedp.ByQuery),
		chromedp.Sleep(2*time.Second),
	); err != nil {
		return fmt.Errorf("chromedp.Run 登录操作 err:%v", err)
	}

	// 获取指定域的所有 cookies
	// 注意：GetCookies 接受 URL 列表，返回对应的 cookies 列表 :contentReference[oaicite:0]{index=0}
	cookies, err := network.GetCookies().WithURLs([]string{loginURL}).Do(ctx)
	if err != nil {
		return fmt.Errorf("network.GetCookies err: %v", err)
	}

	data, err := json.MarshalIndent(cookies, "", "  ")
	if err != nil {
		return fmt.Errorf("json.MarshalIndent err: %v", err)
	}
	fmt.Println("cookies: ", string(data))
	return os.WriteFile(cookieFile, data, 0644)
}

// loadCookies 从文件加载并注入
func loadCookies(ctx context.Context, targetURL string) error {
	b, err := os.ReadFile(cookieFile)
	if err != nil {
		return err
	}
	var cookies []network.Cookie
	if err := json.Unmarshal(b, &cookies); err != nil {
		return err
	}

	// 必须先启用 network 与导航到同域页面
	if err := chromedp.Run(ctx, network.Enable(), chromedp.Navigate(targetURL)); err != nil {
		return err
	}

	for _, c := range cookies {

		// 转换 Expires 类型为 network.TimeSinceEpoch :contentReference[oaicite:1]{index=1}
		exp := cdp.TimeSinceEpoch(time.Unix(int64(c.Expires), 0))
		// SetCookie 的 Do 返回 (bool, error)
		err := network.SetCookie(c.Name, c.Value).
			WithDomain(c.Domain).
			WithPath(c.Path).
			WithExpires(&exp).
			WithHTTPOnly(c.HTTPOnly).
			WithSecure(c.Secure).
			Do(ctx)

		if err != nil {
			log.Printf("注入 Cookie 错误: %v", err)
		}

	}

	// 刷新页面以应用 Cookie
	return chromedp.Run(ctx, chromedp.Reload())
}

// screenshotWithCookies 注入 Cookie 后截图
func screenshotWithCookies(ctx context.Context, url, outPath string, wait time.Duration) error {
	if err := loadCookies(ctx, url); err != nil {
		return err
	}
	// 等待页面异步加载
	time.Sleep(wait)

	var buf []byte
	if err := chromedp.Run(ctx,
		chromedp.FullScreenshot(&buf, 90),
	); err != nil {
		return err
	}
	return os.WriteFile(outPath, buf, 0644)
}

func main() {
	allocCtx, cancelAlloc := initAllocator()
	defer cancelAlloc()

	ctx, cancelCtx := chromedp.NewContext(allocCtx)
	defer cancelCtx()

	ctx, cancelTimeout := context.WithTimeout(ctx, 120*time.Second)
	defer cancelTimeout()

	// 执行登录与保存 Cookie
	if err := performLoginAndSave(ctx, "easyops", "easyops"); err != nil {
		log.Fatalf("登录失败: %v", err)
	}
	// 注入 Cookie 并截图
	target := "https://devops.dev.easyops.local/next/ci/history/00000196c8fb254e6c246093cc9df7a4"
	if err := screenshotWithCookies(ctx, target, "screenshot.png", 5*time.Second); err != nil {
		log.Fatalf("截图失败: %v", err)
	}
	log.Println("截图已保存到 screenshot.png")
}
